package org.xm.sk;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestOperations;
import org.xm.sk.common.ToolsUtil;
import org.xm.sk.common.XmlProcessor;
import org.xm.sk.dao.BoderRepository;
import org.xm.sk.dao.ItemRepository;
import org.xm.sk.dao.TestRepository;
import org.xm.sk.service.data.BaseService;
import org.xm.sk.vo.e.BoderStatus;
import org.xm.sk.vo.ob.Boder2User;
import org.xm.sk.vo.ob.IncludeQuery;
import org.xm.sk.vo.ob.Local;
import org.xm.sk.vo.ob.Payment;
import org.xm.sk.vo.ob.Prepay;
import org.xm.sk.vo.tb.Boder;
import org.xm.sk.vo.tb.Image;
import org.xm.sk.vo.tb.Item;
import org.xm.sk.vo.tb.QTest;
import org.xm.sk.vo.tb.User;

import com.querydsl.core.types.dsl.NumberPath;

import lombok.extern.slf4j.Slf4j;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

//@RunWith(SpringRunner.class)
//@SpringBootTest
@Slf4j
public class SkApplicationTests2 {
    
    private static final String HTTP_UTF_8 = "UTF-8";
    
    @Autowired
    private BoderRepository boderRepository;
    @Autowired
    private BaseService<Boder> boderService;
    /*@Autowired
    private XmlProcessor xmlProcessor;*/
    @Autowired
    private RestOperations restOperations;
    @Autowired
    private BaseService<Image> imageService;

	/*@Test
	public void contextLoads() {
        QTest _Q_test = QTest.test;
        NumberPath<Double> lat = _Q_test.latitude;
        assertThat(this.testRepository.findAll(lat.lt(2))).isEmpty();*/

        /*Calendar cal = Calendar.getInstance();
        cal.add(Calendar.YEAR, -7);
        int year = cal.get(Calendar.YEAR);
        print("" + year);

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.MONTH, -7);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH) + 1;
        print(year + "-" + month);
        print("" + cal.getTime());
        print(year + "-" + month + "-" + cal.getActualMaximum(Calendar.DATE) + " 23:59:59");
        String str = year + "-" + month;
        print(str.substring(str.indexOf("-") + 1));
        print(str.substring(0, str.indexOf("-")));
        print((System.currentTimeMillis() + "").substring(0, 10));

        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DATE, -20);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.get(Calendar.DATE);
        print(year + "-" + month + "-" + day);
	}*/
	
	/*
	@Test
    public void test4Obj2Xml() throws IOException {
	    Payment payment = new Payment();
        payment.setBody("xxxxxdfsdfs");
	    payment.setAppid("sssssssssssssss");
	    payment.setAttach("xxxxxxxxxxxxxxxxx");
	    String xml = xmlProcessor.objectToXML(payment);
	    xml = xml.replaceAll("<\\?.*\\?>\n", "").replaceAll(" xmlns:ns2=\"org.xm.sk\"", "").replace("ns2:payment-info", "xml");
	    print(xml);
        xml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                + "<return_msg><![CDATA[OK]]></return_msg>"
                + "<appid><![CDATA[wx2421b1c4370ec43b]]></appid>"
                + "<mch_id><![CDATA[10000100]]></mch_id>"
                + "<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>"
                + "<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>"
                + "<result_code><![CDATA[SUCCESS]]></result_code>"
                + "<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>"
                + "<trade_type><![CDATA[JSAPI]]></trade_type>" + "</xml>";
        xml = xml.replace("<xml>", "<ns2:prepay-info xmlns:ns2=\"org.xm.sk\">").replaceAll("</xml>", "</ns2:prepay-info>");
        Prepay prepay = (Prepay) xmlProcessor.xmlToObject(xml);
        print(prepay.getAppId());
    }
	*/
	/*
    @Test
    public void test2() {
        Set<Integer> ids = new HashSet<Integer>(0);
        ids.add(1);
        ids.add(2);
        ids.add(3);
        ids.add(4);
        ids.add(6);
        String idsStr = "1,2,3,4,6";
        Pageable pageable = new PageRequest(0, 10);
        Page<Boder2User> page = boderRepository.listMakingByUserId(pageable, 1, BoderStatus.MAKING);
        for (Boder2User item : page.getContent()) {
            for (Integer i : item.getItemIds()) {
                print("i: " + i);
            }
        }
    }
    */
    /*
    @Test
    public void test3() throws IOException {
        Resource resource = new ClassPathResource("instructions.itr");
        InputStream input = resource.getInputStream();
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int n; (n = input.read(b)) != -1;) {
            out.append(new String(b, 0, n, "UTF-8"));
        }
        print(out.toString());
    }
    */
    /*
    @Test
    public void test4() throws IOException {
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<Resource> httpEntity = new HttpEntity<Resource>(headers);
        ResponseEntity<byte[]> response = restOperations.exchange("http://tb1.bdstatic.com/tb/cms/0224fangyuan-04.jpg", HttpMethod.GET,
                httpEntity, byte[].class);
        log.info("===状态码================");
        log.info(">> {}", response.getStatusCodeValue());
        log.info("===返回信息================");
        log.info(">> {}", response.getHeaders().getContentType());
        log.info(">> {}", response.getHeaders().getContentType().getSubtype());
        
        //String url = "http://tb1.bdstatic.com/tb/cms/0224fangyuan-04.jpg";
        //File result = restOperations.getForObject(url, File.class);
        //print(result.getName());
        Image image = new Image();
        image.setName("test1");
        image.setFile(response.getBody());
        imageService.add(image);
    }
    
    @SuppressWarnings("unchecked")
    @Test
    public void test() {
        //print(ToolsUtil.matchDateString("1/1 01"));
        Set<String> ordernums = new HashSet<String>(0);
        ordernums.add("B195192877800079360");
        ordernums.add("B195193910023245824");
        ordernums.add("B195193917128396801");
        Set<Boder> orderList = boderRepository.findByOrdernumIn(ordernums);
        assertNotNull(orderList);
        assertFalse(orderList.isEmpty());
        assertNotEquals(3, orderList.size());
        IncludeQuery includeQuery = new IncludeQuery("ordernum", ordernums);
        Object o = boderService.findAllByPage(null, includeQuery);
        Set<Boder> list = (Set<Boder>) o;
        assertNotNull(list);
        assertFalse(list.isEmpty());
        assertEquals(2, list.size());
    }
    */
    //@Test
    public void test() throws Exception {
        String encData = "CT1r7k2rDGlZMgO6+TxbhP9EpRq++a2ex5oBOxMVWPcs8y6TeF3hreypF1K+4zrnzmgfoVjjsaIFxKH68KopV8kHR/CXC4/ilhRKAPr1nhDXqAavdNx+0HcHLgybVeuBcKKDueFYfNg10xuI6gCZppk4YBc0IelcAGvYimqj1WRQ6As+D/o7WsPabYx9KfRPO+nbmh0hN5XKyY2C1wk16w==";
        String iv = "BQzfu9+An/EafCdUtAcpaw==";
        String session_key = ToolsUtil.desencrypt("dA4NoGXYX3OsNTU8+Kx5pGQZpJtHw9xiHKlRvynChtw=");
        byte[] encrypData = ToolsUtil.decodeBase64(encData);
        byte[] ivData = ToolsUtil.decodeBase64(iv);
        byte[] sessionKey = ToolsUtil.decodeBase64(session_key);
        log.info("{}", sessionKey.length);
        byte[] dd = ToolsUtil.asedecrypt(sessionKey, ivData, encrypData);
        //log.info(decrypt(encrypData, "UTF-8", sessionKey, ivData));
        log.info(new String(dd, "UTF-8"));
    }

    // 解密
    public String decrypt(byte[] encrypted1, String encodingFormat, byte[] raw,
            byte[] ivParameter) throws Exception {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, encodingFormat);
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public static byte[] decrypt(byte[] key, byte[] iv, byte[] encData)
            throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException,
            BadPaddingException, IllegalBlockSizeException {
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
        cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
        return cipher.doFinal(encData);
    }
    
    public static <T> boolean isNumeric(String str, T t) {
        if (t instanceof Integer) {
            Pattern pattern = Pattern.compile("^([1-9]\\d*|0)$");
            return pattern.matcher(str).matches();
        } else {
            Pattern pattern = Pattern.compile("^([1-9]\\d*|0)(\\.\\d+)+$");
            return pattern.matcher(str).matches();
        }
    }
    
    public byte[] read(File file) throws IOException {
        ByteArrayOutputStream ous = null;
        InputStream ios = null;
        try {
            byte[] buffer = new byte[4096];
            ous = new ByteArrayOutputStream();
            ios = new FileInputStream(file);
            int read = 0;
            while ((read = ios.read(buffer)) != -1) {
                ous.write(buffer, 0, read);
            }
        }finally {
            try {
                if (ous != null)
                    ous.close();
            } catch (IOException e) {
            }

            try {
                if (ios != null)
                    ios.close();
            } catch (IOException e) {
            }
        }
        return ous.toByteArray();
    }
    
	protected void print(String str) {
	    System.out.println(str);
	}

}
